using System;
using System.Data;

namespace CustomORM.Extensions
{
    public static class DataReaderExtensions
    {
        public static T Field<T>(this IDataReader rdr, String column)
        {
            if (rdr[column] == DBNull.Value)
            {
                object default_obj = null;

                if (typeof(T) == typeof(Boolean)) default_obj = false;
                else if (typeof(T) == typeof(SByte)) default_obj = (SByte)0;
                else if (typeof(T) == typeof(Int16)) default_obj = (Int16)0;
                else if (typeof(T) == typeof(Int32)) default_obj = 0;
                else if (typeof(T) == typeof(Int64)) default_obj = (Int64)0;
                else if (typeof(T) == typeof(Byte)) default_obj = (Byte)0;
                else if (typeof(T) == typeof(UInt16)) default_obj = (UInt16)0;
                else if (typeof(T) == typeof(UInt32)) default_obj = (UInt32)0;
                else if (typeof(T) == typeof(UInt64)) default_obj = (UInt64)0;
                else if (typeof(T) == typeof(Single)) default_obj = (Single)0;
                else if (typeof(T) == typeof(Double)) default_obj = (Double)0;
                else if (typeof(T) == typeof(Char)) default_obj = '\0';
                else if (typeof(T) == typeof(String)) default_obj = null; // we might want to have here String.Empty
                else if (typeof(T) == typeof(DateTime)) default_obj = System.Data.SqlTypes.SqlDateTime.MinValue.Value;
                else if (typeof(T) == typeof(Decimal)) default_obj = Decimal.Zero;
                else if (typeof(T) == typeof(Guid)) default_obj = Guid.Empty;

                return (T)default_obj;
            }
            else
            {
                object ret_obj = null;

                if (typeof(T) == typeof(Boolean)) ret_obj = Convert.ToBoolean(rdr[column]);
                else if (typeof(T) == typeof(SByte)) ret_obj = Convert.ToSByte(rdr[column]);
                else if (typeof(T) == typeof(Int16)) ret_obj = Convert.ToInt16(rdr[column]);
                else if (typeof(T) == typeof(Int32)) ret_obj = Convert.ToInt32(rdr[column]);
                else if (typeof(T) == typeof(Int64)) ret_obj = Convert.ToInt64(rdr[column]);
                else if (typeof(T) == typeof(Byte)) ret_obj = Convert.ToByte(rdr[column]);
                else if (typeof(T) == typeof(UInt16)) ret_obj = Convert.ToUInt16(rdr[column]);
                else if (typeof(T) == typeof(UInt32)) ret_obj = Convert.ToUInt32(rdr[column]);
                else if (typeof(T) == typeof(UInt64)) ret_obj = Convert.ToUInt64(rdr[column]);
                else if (typeof(T) == typeof(Single)) ret_obj = Convert.ToSingle(rdr[column]);
                else if (typeof(T) == typeof(Double)) ret_obj = Convert.ToDouble(rdr[column]);
                else if (typeof(T) == typeof(Char)) ret_obj = Convert.ToChar(rdr[column]);
                else if (typeof(T) == typeof(String)) ret_obj = Convert.ToString(rdr[column]);
                else if (typeof(T) == typeof(DateTime)) ret_obj = Convert.ToDateTime(rdr[column]);
                else if (typeof(T) == typeof(Decimal)) ret_obj = Convert.ToDecimal(rdr[column]);
                else if (typeof(T) == typeof(Guid)) ret_obj = new Guid(Convert.ToString(rdr[column]));

                return (T)ret_obj;
            }

            //return default(T);
        }

        public static Nullable<T> NullableField<T>(this IDataReader rdr, String column) where T : struct
        {
            if (rdr[column] == DBNull.Value)
            {
                return null;
            }
            else
            {
                object ret_obj = null;

                if (typeof(T) == typeof(Boolean)) ret_obj = Convert.ToBoolean(rdr[column]);
                else if (typeof(T) == typeof(SByte)) ret_obj = Convert.ToSByte(rdr[column]);
                else if (typeof(T) == typeof(Int16)) ret_obj = Convert.ToInt16(rdr[column]);
                else if (typeof(T) == typeof(Int32)) ret_obj = Convert.ToInt32(rdr[column]);
                else if (typeof(T) == typeof(Int64)) ret_obj = Convert.ToInt64(rdr[column]);
                else if (typeof(T) == typeof(Byte)) ret_obj = Convert.ToByte(rdr[column]);
                else if (typeof(T) == typeof(UInt16)) ret_obj = Convert.ToUInt16(rdr[column]);
                else if (typeof(T) == typeof(UInt32)) ret_obj = Convert.ToUInt32(rdr[column]);
                else if (typeof(T) == typeof(UInt64)) ret_obj = Convert.ToUInt64(rdr[column]);
                else if (typeof(T) == typeof(Single)) ret_obj = Convert.ToSingle(rdr[column]);
                else if (typeof(T) == typeof(Double)) ret_obj = Convert.ToDouble(rdr[column]);
                else if (typeof(T) == typeof(Char)) ret_obj = Convert.ToChar(rdr[column]);
                else if (typeof(T) == typeof(String)) ret_obj = Convert.ToString(rdr[column]);
                else if (typeof(T) == typeof(DateTime)) ret_obj = Convert.ToDateTime(rdr[column]);
                else if (typeof(T) == typeof(Decimal)) ret_obj = Convert.ToDecimal(rdr[column]);
                else if (typeof(T) == typeof(Guid)) ret_obj = new Guid(Convert.ToString(rdr[column]));

                return (T)ret_obj;
            }

            //return default(T);
        }
    }
}